
//编译 g++ echo_server.cpp -lboost_system -lboost_chrono
#include "grpc.grpc.pb.h"
#include <grpcpp/grpcpp.h>
#include <memory>
#include <iostream>
#include<mutex>

#include <websocketpp/config/asio_no_tls.hpp>
 
#include <websocketpp/server.hpp>

#include<string>
#include<unordered_map>
#include <bits/std_function.h> //添加function头文件
 
typedef websocketpp::server<websocketpp::config::asio> server;
pthread_mutex_t mt;

using websocketpp::lib::bind;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
 std::unordered_map<std::string,std::string> rm;
// pull out the type of messages sent by our config
typedef server::message_ptr message_ptr;

 std::unordered_map<std::string,websocketpp::connection_hdl> m;
 
std::shared_ptr<grpc::Channel> channel =grpc::CreateChannel("localhost:33333", grpc::InsecureChannelCredentials());
       // 创建一个stub
std::unique_ptr<Rpc::Server::Stub> stub = Rpc::Server::NewStub(channel);

// std::list<websocketpp::connection_hdl> vgdl;
// void serversend(server *s)
// {
//     message_ptr tmp;
//     std::string ret="server send 主动";
//     std::cout<<"send"<<std::endl;

//      s->send(m[0],ret, websocketpp::frame::opcode::text);
// }

// Define a callback to handle incoming messages
  server sr;
void on_message(server *s, websocketpp::connection_hdl hdl, message_ptr msg)
{
    // std::cout << "on_message called with hdl: " << hdl.lock().get()
    //           << " and message: " << msg->get_payload()
    //           << std::endl;
 
    // check for a special command to instruct the server to stop listening so
    // it can be cleanly exited.
    if (msg->get_payload() == "stop-listening")
    {
        s->stop_listening();
        return;
    }
    std::cout<<"server receive:   "<<msg->get_payload()<<std::endl;
    std::string st=msg->get_payload();
    
    ssize_t index=st.find(":",0);
    std::string event=st.substr(0,index);
    std::cout<<"event"<<event<<std::endl;
    if(event=="regret")
    {
        st=std::string(st.begin()+index+1,st.end());
        std::cout<<st<<std::endl;

        index=st.find(":",0);
         std::cout<<index<<std::endl;
        std::string sender=st.substr(0,index);
        
        st=std::string(st.begin()+index+1,st.end());
        //sender:user_id room_id

        // std::cout<<sender<<std::endl;
        // std::cout<<st<<std::endl;   
        //grpc通信
       pthread_mutex_lock(&mt);
          // 创建一个请求对象，用于打包要发送的请求数据
           Rpc::MkdirRequest request;
           // 创建一个响应对象，用于解包响要接收的应数据
           Rpc::MkdirReply   reply;
           
           // 创建一个客户端上下文。它可以用来向服务器传递附加的信息，以及可以调整某些RPC行为                               
           grpc::ClientContext context;
            request.set_room_id(st);
            request.set_my_id(sender);
            // 发送请求，接收响应
            grpc::Status st = stub->QueryOpponent(&context,request,&reply);
            if(st.ok()){
                // 输出下返回数据   
                //添加map
                rm[reply.oppid()]=sender;
                rm[sender]=reply.oppid();
                std::cout<< "oppid = " << reply.oppid()<<std::endl;
                std::string send="regret:"+sender;
                std::cout<<send<<std::endl;
                s->send(m[reply.oppid()],send, websocketpp::frame::opcode::text);
            }
            else
            {
                std::cout<<"rpc error"<<std::endl;
            }

       pthread_mutex_unlock(&mt);
    }
    else if(event=="agree")
    {
        st=std::string(st.begin()+index+1,st.end());
        std::cout<<st<<std::endl;
        s->send(m[rm[st]],"agree", websocketpp::frame::opcode::text);
    }
    else if(event=="agree2")
    {
        st=std::string(st.begin()+index+1,st.end());
        std::cout<<st<<std::endl;
        s->send(m[rm[st]],"agree2", websocketpp::frame::opcode::text);
    }
    else if(event=="ack")
    {
        //反推对面id
        st=std::string(st.begin()+index+1,st.end());
        std::cout<<st<<std::endl;
        s->send(m[rm[st]],"ack:", websocketpp::frame::opcode::text);
    }
    else if(event=="refuse")
    {
        st=std::string(st.begin()+index+1,st.end());
        std::cout<<st<<std::endl;
        s->send(m[rm[st]],"refuse:", websocketpp::frame::opcode::text);
    }
    //s->send(hdl, msg->get_payload(), msg->get_opcode());

}
int i=0;
//将每个连接存入容器
void on_open(websocketpp::connection_hdl hdl)
{

    server::connection_ptr con = sr.get_con_from_hdl(hdl);
    websocketpp::http::parser::request rt = con->get_request();
    const std::string strUri = rt.get_uri();

    //std::cout<<strUri<<std::endl;///?usr_id=49
    ssize_t index=strUri.rfind("=");
    std::string id=std::string(strUri.begin()+index+1,strUri.end());
    // std::cout<<id<<std::endl;
    m[id]=hdl;
    std::cout<<"连接到来 "<<id<<std::endl;
    // std::string msg = "link OK";
    // printf("%s\n", msg.c_str());
    // m[i++]=hdl;
    // // printf("fd %d\n",(int)hdl._M_ptr());
    // vgdl.push_back(hdl);
}

// void on_http( websocketpp::connection_hdl hdl) {
// 	server::connection_ptr con = sr->get_con_from_hdl(hdl);
 
// 	std::string res = con->get_request_body();
 
// 	std::stringstream ss;
// 	ss << "got HTTP request with " << res.size() << " bytes of body data.";
 
// 	con->set_body(ss.str());
// 	con->set_status(websocketpp::http::status_code::ok);
// }

void on_close(websocketpp::connection_hdl hdl)
{
    std::string msg = "close OK";
    printf("%s\n", msg.c_str());
}
 // Create a server endpoint

int main()
{

    pthread_mutex_init(&mt, NULL);
    try
    {
          // 创建一个连接服务器的通道

        // Set logging settings 设置log
       sr.set_access_channels(websocketpp::log::alevel::all);
        sr.clear_access_channels(websocketpp::log::alevel::frame_payload);
 
        // Initialize Asio 初始化asio
        sr.init_asio();
 
        // Register our message handler
        // 绑定收到消息后的回调
        sr.set_message_handler(bind(&on_message, &sr, ::_1, ::_2));
        //当有客户端连接时触发的回调
        std::function<void(websocketpp::connection_hdl)> f_open;
        f_open = on_open;
        sr.set_open_handler(websocketpp::open_handler(f_open));
        //关闭是触发
        std::function<void(websocketpp::connection_hdl)> f_close(on_close);
        sr.set_close_handler(f_close);
        std::cout<<"123"<<std::endl;
        // Listen on port 9002
        sr.listen(8083);//监听端口
 
        // Start the server accept loop
        sr.start_accept();
 
        // Start the ASIO io_service run loop
        sr.run();
    }
    catch (websocketpp::exception const &e)
    {
        std::cout << e.what() << std::endl;
    }
    catch (...)
    {
        std::cout << "other exception" << std::endl;
    }
}